/**
 *  This file is part of PennerBot
 *
 *  Copyright (C) 2010 microkernel
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//TODO americanformat
//TODO savetofile

#include <fstream>

#include <extern/tinyxml/tinyxml.h>

#include <core/configparser.hpp>

namespace PBot
{
namespace Core
{

ConfigParser::ConfigParser()
{
}

ConfigParser::~ConfigParser()
{
}

ConfigParser::status ConfigParser::LoadFromFile(const std::string& filename, Config **cfg)
{
    std::vector<Config*> configs;

    ConfigParser::status res = LoadFromFile(filename, configs);

    if(configs.size() > 0)
    {
        *cfg = configs[0];
    }
    else
    {
        *cfg = NULL;
    }

    return res;
}

ConfigParser::status ConfigParser::LoadFromFile(const std::string& filename,
        std::vector<Config*>& configs)
{
    TiXmlDocument doc(filename);

    if(!doc.LoadFile())
    {
        return FILE_OPEN_ERROR;
    }

    TiXmlHandle hDoc(&doc);
    TiXmlElement* pElem;
    TiXmlHandle hRoot(0);

    pElem = hDoc.FirstChildElement().Element();

    if(!pElem)
    {
        return FILE_NOT_SUPPORTED;
    }

    hRoot = TiXmlHandle(pElem);

    if(pElem->Value() == std::string("pennerconfig"))
    {
        int i = 0;

        while(true)
        {
            pElem = hRoot.Child("pennerbot", i).FirstChild().Element();
            if(!pElem)
                break;

            Config *cfg = new Config;
            cfg->id = i;

            for(; pElem; pElem = pElem->NextSiblingElement())
            {

                if(pElem->ValueStr() == "name")
                {
                    if(pElem->GetText())
                    {
                        cfg->botname = pElem->GetText();
                    }
                }
                else if(pElem->ValueStr() == "username")
                {
                    if(pElem->GetText())
                    {
                        cfg->username = pElem->GetText();
                    }
                }
                else if(pElem->ValueStr() == "password")
                {
                    if(pElem->GetText())
                    {
                        cfg->password = pElem->GetText();
                    }
                }
                else if(pElem->ValueStr() == "game")
                {
                    if(pElem->GetText())
                    {
                        if(std::string(pElem->GetText()) == "pennergame_h")
                        {
                            cfg->game = Config::PENNERGAME_H;
                            cfg->website = "http://www.pennergame.de";
                        }
                        else if(std::string(pElem->GetText()) == "pennergame_b")
                        {
                            cfg->game = Config::PENNERGAME_B;
                            cfg->website = "http://berlin.pennergame.de";
                        }
                        else if(std::string(pElem->GetText()) == "pennergame_m")
                        {
                            cfg->game = Config::PENNERGAME_M;
                            cfg->website = "http://muenchen.pennergame.de";
                        }
                        else if(std::string(pElem->GetText()) == "dossergame")
                        {
                            cfg->game = Config::DOSSERGAME;
                            cfg->website = "http://www.dossergame.co.uk";
                        }
                        else if(std::string(pElem->GetText()) == "menelgame_w")
                        {
                            cfg->game = Config::MENELGAME_W;
                            cfg->website = "http://www.menelgame.pl";
                        }
                        else if(std::string(pElem->GetText()) == "menelgame_k")
                        {
                            cfg->game = Config::MENELGAME_K;
                            cfg->website = "http://krakow.menelgame.pl";
                        }
                        else if(std::string(pElem->GetText()) == "clodogame_p")
                        {
                            cfg->game = Config::CLODOGAME_P;
                            cfg->website = "http://www.clodogame.fr";
                        }
                        else if(std::string(pElem->GetText()) == "clodogame_m")
                        {
                            cfg->game = Config::CLODOGAME_M;
                            cfg->website = "http://marseille.clodogame.fr";
                        }
                        else if(std::string(pElem->GetText()) == "mendigogame")
                        {
                            cfg->game = Config::MENDIGOGAME;
                            cfg->website = "http://www.mendigogame.es";
                        }
                        else if(std::string(pElem->GetText()) == "serserionline")
                        {
                            cfg->game = Config::SERSERIONLINE;
                            cfg->website = "http://www.serserionline.com";
                        }
                        else if(std::string(pElem->GetText()) == "bumrise")
                        {
                            cfg->game = Config::BUMRISE;
                            cfg->website = "http://www.bumrise.com";
                            cfg->americanFormat = true;
                        }
                        else if(std::string(pElem->GetText()) == "faveladogame")
                        {
                            cfg->game = Config::FAVELADOGAME;
                            cfg->website = "http://www.faveladogame.com.br";
                        }
                        else if(std::string(pElem->GetText()) == "malle")
                        {
                            cfg->game = Config::MALLE;
                            cfg->website = "http://malle.pennergame.de";
                        }
                        else if(std::string(pElem->GetText()) == "pennergame_k")
                        {
                            cfg->game = Config::KOELN;
                            cfg->website = "http://koeln.pennergame.de";
                            cfg->hasCaptcha = false;
                        }
                    }
                }
                else if(pElem->ValueStr() == "useragent")
                {
                    if(pElem->GetText())
                    {
                        cfg->userAgent = pElem->GetText();
                    }
                }
                else if(pElem->ValueStr() == "proxy")
                {
                    if(pElem->GetText())
                    {
                        cfg->proxy = pElem->GetText();
                    }
                }
                else if(pElem->ValueStr() == "bottlecollect")
                {
                    std::string tmp;
                    pElem->QueryStringAttribute("enabled", &tmp);

                    if(tmp == "true")
                    {
                        cfg->BC_enabled = true;
                    }
                    else
                    {
                        cfg->BC_enabled = false;
                    }

                    pElem->QueryValueAttribute("minwait", &(cfg->BC_minwait));
                    pElem->QueryValueAttribute("maxwait", &(cfg->BC_maxwait));
                    pElem->QueryValueAttribute("thirtyminprobability", &(cfg->BC_thirtyminprobability));

                    pElem->QueryStringAttribute("usejunk", &tmp);

                    if(tmp == "true")
                    {
                        cfg->BC_usejunk = true;
                    }
                    else
                    {
                        cfg->BC_usejunk = false;
                    }
                }
                else if(pElem->ValueStr() == "bottlesell")
                {
                    std::string tmp;
                    pElem->QueryStringAttribute("enabled", &tmp);

                    if(tmp == "true")
                    {
                        cfg->BS_enabled = true;
                    }
                    else
                    {
                        cfg->BS_enabled = false;
                    }

                    pElem->QueryValueAttribute("maxmoney", &(cfg->BS_maxMoney));
                    pElem->QueryValueAttribute("minexchange", &(cfg->BS_minExchange));
                }

#ifdef PBOT_SPECIAL

                else if(pElem->ValueStr() == "autoskill")
                {
                    std::string tmp;
                    pElem->QueryStringAttribute("enabled", &tmp);

                    if(tmp == "true")
                    {
                        cfg->AS_enabled = true;
                    }
                    else
                    {
                        cfg->AS_enabled = false;
                    }

                    pElem->QueryStringAttribute("skills", &tmp);

                    size_t pos = 0, oldpos = 0;
                    while(true)
                    {
                        pos = tmp.find(' ', oldpos);
                        std::string sub = tmp.substr(oldpos, pos-oldpos);
                        oldpos = pos+1;

                        if(sub == "att")
                        {
                            cfg->skills.push_back(Config::ATT);
                        }
                        else if(sub == "def")
                        {
                            cfg->skills.push_back(Config::DEF);
                        }
                        else if(sub == "dex")
                        {
                            cfg->skills.push_back(Config::DEX);
                        }
                        else if(sub == "speech")
                        {
                            cfg->skills.push_back(Config::SPEECH);
                        }
                        else if(sub == "edu")
                        {
                            cfg->skills.push_back(Config::EDU);
                        }
                        else if(sub == "music")
                        {
                            cfg->skills.push_back(Config::MUSIC);
                        }
                        else if(sub == "social")
                        {
                            cfg->skills.push_back(Config::SOCIAL);
                        }
                        else if(sub == "concentration")
                        {
                            cfg->skills.push_back(Config::CONCENTRATION);
                        }
                        else if(sub == "pickpocket")
                        {
                            cfg->skills.push_back(Config::PICKPOCKET);
                        }

                        if(pos == std::string::npos)
                        {
                            break;
                        }
                    }
                }

#endif /* PBOT_SPECIAL */

            }

            configs.push_back(cfg);

            if(cfg->username.empty())
            {
                return MISSING_USERNAME;
            }
            else if(cfg->password.empty())
            {
                return MISSING_PASSWORD;
            }
            else if(cfg->userAgent.empty())
            {
                return MISSING_USERAGENT;
            }
            else if(cfg->website.empty())
            {
                return MISSING_GAME;
            }

            ++i;
        }
    }
    else
    {
        return FILE_NOT_SUPPORTED;
    }

    return ALL_CLEAR;
}

ConfigParser::status ConfigParser::SaveToFile(const std::string& filename, Config *cfg)
{
    std::vector<Config*> temp;
    temp.push_back(cfg);

    return SaveToFile(filename, temp);
}


ConfigParser::status ConfigParser::SaveToFile(const std::string& filename, std::vector<Config*>& configs)
{
    std::ofstream file(filename.c_str());

    if(file)
    {
        file << "<?xml version=\"1.0\" ?>" << std::endl;
        file << "<pennerconfig>" << std::endl;

        for(std::vector<Config*>::iterator i(configs.begin()), end(configs.end()); i != end; ++i)
        {
            file << "  <pennerbot>" << std::endl;

            file << "    <name>" << (*i)->botname << "</name>" << std::endl;
            file << "    <username>" << (*i)->username << "</username>" << std::endl;
            file << "    <password>" << (*i)->password << "</password>" << std::endl;

            file << "    <game>";

            switch((*i)->game)
            {
                case Config::PENNERGAME_H:
                    file << "pennergame_h";
                    break;

                case Config::PENNERGAME_B:
                    file << "pennergame_b";
                    break;

                case Config::PENNERGAME_M:
                    file << "pennergame_m";
                    break;

                case Config::DOSSERGAME:
                    file << "dossergame";
                    break;

                case Config::MENELGAME_W:
                    file << "menelgame_w";
                    break;

                case Config::MENELGAME_K:
                    file << "menelgame_k";
                    break;

                case Config::CLODOGAME_P:
                    file << "clodogame_p";
                    break;

                case Config::CLODOGAME_M:
                    file << "clodogame_m";
                    break;

                case Config::MENDIGOGAME:
                    file << "mendigogame";
                    break;

                case Config::SERSERIONLINE:
                    file << "serserionline";
                    break;

                case Config::BUMRISE:
                    file << "bumrise";
                    break;

                case Config::FAVELADOGAME:
                    file << "faveladogame";
                    break;

                case Config::MALLE:
                    file << "malle";
                    break;

                case Config::KOELN:
                    file << "pennergame_k";
                    break;
            }

            file << "</game>" << std::endl;

            file << "    <useragent>" << (*i)->userAgent << "</useragent>" << std::endl;
            file << "    <proxy>" << (*i)->proxy << "</proxy>" << std::endl;

            file << "    <bottlecollect enabled=\"";

                file << ((*i)->BC_enabled ? "true" : "false");
                file << "\" minwait=\"";
                file << (*i)->BC_minwait;
                file << "\" maxwait=\"";
                file << (*i)->BC_maxwait;
                file << "\" thirtyminprobability=\"";
                file << (*i)->BC_thirtyminprobability;
                file << "\" usejunk=\"";
                file << ((*i)->BC_usejunk ? "true" : "false");
                file << "\" />" << std::endl;

            file << "  </pennerbot>" << std::endl;
        }

        file << "</pennerconfig>" << std::endl;

        file.close();
    }
    else
    {
        return FILE_OPEN_ERROR;
    }

    return ALL_CLEAR;
}

}
}
